home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Everything For A Hacker
/
19990506-[HACK].iso
/
HEXEDIT
/
UTILS
/
BLUEBOOK.ARJ
/
FLOATPT.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-05-14
|
23KB
|
843 lines
COMMENT ~
FLOATPT.ASM -- Floating Point Conversion Procedures
From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
by Christopher L. Morgan
Copyright (C) 1984 by The Waite Group, Inc.
Purpose:
Contents:
---------
BIN802DEC -- Convert from 80-bit binary to decimal digits
DECDOUBLE -- Double a temporary decimal floating point number
DECHALF -- Halve a temporary decimal floating point number
DECNORM -- Normalize temporary decimal floating point
DFP2SFP -- Convert from double to single precision floating point
FIX -- Convert from floating point to 16-bit integer
FLOAT -- Convert from 16-bit integer to floating point
FPIN -- Convert from external to internal floating point
FPINDIGIT -- Input single decimal digit to floating point
FPOUT -- Convert from internal to external floating point
FPTDIV -- Divide temporary floating point by 10
FPTMUL -- Multiply temporary floating point by 10
FPTNORM -- Normalize temporary floating point
SFP2DFP -- Convert from single to double precision floating point
SFP2TFP -- Convert from single precision to temporary floating point
SGNDEC16IN -- Convert from ASCII signed decimal to binary
TDECSHOW -- Display floating point
TFP2SFP -- Convert from temporary floating point to single precision
_____________________________________________________________________________
~
CODES SEGMENT
EXTRN STDIN:FAR,STDOUT:FAR
PUBLIC SGNDEC16IN,TFP2SFP,FPINDIGIT,FPTNORM,FPTMUL,FPTDIV,FPIN
PUBLIC SFP2TFP,TDECSHOW,BIN802DEC,DECNORM,DECHALF,DECDOUBLE,FPOUT
PUBLIC FIX,FLOAT,SFP2DFP,DFP2SFP,MBINADD,MBINSUB,MBINMUL,MBINDIV
ASSUME CS:CODES,DS:DATAS
;Equates
SIBYTE EQU BYTE PTR [SI]
SIWORD EQU WORD PTR [SI]
DIBYTE EQU BYTE PTR [DI]
DIWORD EQU WORD PTR [DI]
SFPBUFFW0 EQU WORD PTR SFPBUFF+0
SFPBUFFB2 EQU BYTE PTR SFPBUFF+2
SFPBUFFB3 EQU BYTE PTR SFPBUFF+3
SFPBUFFW2 EQU WORD PTR SFPBUFF+2
DFPBUFFW0 EQU WORD PTR DFPBUFF+0
DFPBUFFW2 EQU WORD PTR DFPBUFF+2
DFPBUFFW4 EQU WORD PTR DFPBUFF+4
DFPBUFFW6 EQU WORD PTR DFPBUFF+6
FPTEMP1W0 EQU WORD PTR FPTEMP1+0
FPTEMP1W2 EQU WORD PTR FPTEMP1+2
FPTEMP1W4 EQU WORD PTR FPTEMP1+4
FPTEMP1W6 EQU WORD PTR FPTEMP1+6
FPTEMP1W8 EQU WORD PTR FPTEMP1+8
FPTEMP1B10 EQU BYTE PTR FPTEMP1+10
FPTEMP1W11 EQU WORD PTR FPTEMP1+11
FPTEMP2W0 EQU WORD PTR FPTEMP2+0
FPTEMP2W2 EQU WORD PTR FPTEMP2+2
FPTEMP2W4 EQU WORD PTR FPTEMP2+4
FPTEMP2W6 EQU WORD PTR FPTEMP2+6
FPTEMP2W8 EQU WORD PTR FPTEMP2+8
FPTEMP2B10 EQU BYTE PTR FPTEMP2+10
FPTEMP2W11 EQU WORD PTR FPTEMP2+11
;__________________________ FLOATING POINT ROUTINES __________________________
;-----------------------------------------------------------------------------
;Convert from 80-bit binary to decimal digits
BIN802DEC PROC NEAR
;
;Clear the string
PUSH DI ;Save destination pointer
MOV AL,0 ;Zero byte
MOV CX,25 ; for a count of 25
BIN802DEC1:
MOV [DI],AL ;Zero the byte
INC DI ;Point to next byte
LOOP BIN802DEC1 ; until done
POP DI ;Restore destination pointer
;
;Keep looping
BIN802DEC2:
PUSH SI ;Save source pointer
;
;Divide mantissa by 10
MOV BX,0 ;Done flag
MOV CX,5 ;5 words in number
MOV DX,0 ;Previous remainder
ADD SI,8 ;Point to high end
BIN802DEC3:
PUSH CX ;Save count
MOV AX,[SI] ;Get 16-bit digit
MOV CX,10 ;Divisor of 10
DIV CX ;Divide
MOV [SI],AX ;Put 16-bit digit back
OR BX,AX ;Check for zero
SUB SI,2 ;Point to next 16-bit digit
POP CX ;Restore count
LOOP BIN802DEC3
MOV [DI],DL ;Remainder is decimal digit
INC DI ;Point to next decimal digit
POP SI ;Restore source pointer
CMP BX,0 ;Was the binary zero ?
JNZ BIN802DEC2 ; if so, loop
RET ; else return
BIN802DEC ENDP
;-----------------------------------------------------------------------------
;Double a temporary decimal floating point number
DECDOUBLE PROC NEAR
MOV CX,25 ;For a count of 25
MOV AH,0 ;Clear previous carry
DECDOUBLE1:
MOV AL,[DI] ;Get digit
SAL AL,1 ;Multiply by 2
ADD AL,AH ;Add the carry
AAM ;Adjust for dec multiplication
MOV [DI],AL ;Put the byte back
INC DI ;Point to next byte
LOOP DECDOUBLE1
RET
DECDOUBLE ENDP
;-----------------------------------------------------------------------------
;Halve a temporary decimal floating point number
DECHALF PROC NEAR
;
;First shift up one digit
MOV CX,25 ;For a count of 25
MOV AL,0 ;Zero previous digit
DECHALF1:
XCHG AL,[DI] ;Exchange with current digit
INC DI ;Point to next digit
LOOP DECHALF1
DEC DECEXP ;Decrement decimal digit
;
;Now divide by 2
MOV CX,25 ;For a count of 25
MOV AH,0 ;Clear carry
DECHALF2:
PUSH CX ;Save count
DEC DI ;Point to next digit
MOV AL,[DI] ;Get the digit
MOV CL,2 ;Divisor of 2
AAD ;Adjust for decimal division
DIV CL ;Divide
MOV [DI],AL ;Put it back
POP CX ;Restore count
LOOP DECHALF2
RET
DECHALF ENDP
;-----------------------------------------------------------------------------
;Normalize a temporary decimal floating point number
DECNORM PROC NEAR
;
;Check top + 1 digit
CMP DIBYTE+22,0 ;Is it already zero ?
JE DECNORM_XIT ;If so, go
;
;Round up, starting with bottom digit
MOV AL,[DI] ;First digit
ADD AL,AL ;Double it for rounding
MOV AH,0 ;Prepare carry
AAA ;Adjust for decimal
;
;Now shift the rest
MOV CX,24 ;For a count of 24
DECNORM1:
MOV AL,[DI+1] ;Get next digit
ADD AL,AH ;Add carry
MOV AH,0 ;Prepare next carry
AAA ;Adjust for decimal
MOV [DI],AL ;Put digit in place
INC DI ;Point to next digit
LOOP DECNORM1
INC DECEXP ;Increment decimal exponent
DECNORM_XIT:
RET
DECNORM ENDP
;-----------------------------------------------------------------------------
;Convert from double to single precision floating point
DFP2SFP PROC FAR
PUSH AX ;Save register
MOV AX,DFPBUFFW4 ;Get word from double precision
MOV SFPBUFFW0,AX ;Put it in single precision
MOV AX,DFPBUFFW6 ;Get word from double precision
MOV SFPBUFFW2,AX ;Put it in single precision
PUSH AX ;Restore register
RET
DFP2SFP ENDP
;-----------------------------------------------------------------------------
;Convert from internal floating point to internal 16-bit integer (truncate)
FIX PROC FAR
;
;The number is in SFPBUFF
PUSH CX ;Save registers
PUSH AX
;
;Get the mantissa
MOV AX,SFPBUFFW0 ;AX gets low part
MOV AX,SFPBUFFW2 ;DX gets high part
AND DX,007FH ;Just the mantissa
OR DX,0080H ;Restore the MSB
;
;Get the exponent
MOV CL,SFPBUFFB3
MOV CH,0 ;Extend to 16-bit
SUB CX,88H ;Subtract bias +
CMP CX,0 ;Check its sign
JL FIX1 ; if negative
JG FIX3 ; if positive
JE FIX4 ; if zero
;
;Shift right
FIX1:
NEG CX ;Absolute value
FIX2:
SAR DX,1 ;Shift all bits right
RCR AX,1 ;Carry on
LOOP FIX2
JMP FIX4 ;End of case negative
;
;Shift left
FIX3:
SAL AX,1 ;Shift all bits left
RCL DX,1 ;Carry on
LOOP FIX3
JMP FIX4 ;End of case positive
;
;Check the sign
FIX4:
MOV AL,SFPBUFFB2 ;Get sign
AND AL,80H ;Just bit 7
JZ FIX_XIT ;Is it on ?
NEG DX ;Two's complement if negative
;
FIX_XIT:
POP AX ;Restore registers
POP CX
RET
FIX ENDP
;-----------------------------------------------------------------------------
;Convert from 16-bit integer to floating point
FLOAT PROC FAR
;
;The number is in DX
PUSH DX ;Save registers
PUSH CX
PUSH AX
MOV AX,0 ;Extend to 32 bits
CMP DX,0 ;Check if zero
JZ FLOAT4
FLOAT1:
MOV CX,9800H ;Initialize exponent & sign
;
;Shift left until normalized
FLOAT2:
TEST AX,0080H ;Done yet ?
JNZ FLOAT3 ;If so, go
SAL DX,1 ;If not, shift all bits left
RCL AX,1 ;Carry on
DEC CH ;Decrement the exponent
JMP FLOAT2
;
;Pack it in
FLOAT3:
AND AX,007FH ;Just the mantissa
OR AX,CX ;Exponent and sign
FLOAT4:
MOV SFPBUFFW0,DX ;Put lower part into place
MOV SFPBUFFW2,AX ;Put upper part into place
;
;Show hex for debugging
LEA SI,INTERNAL ;Point to message
CALL STDMSG_OUT ;Send it
MOV DX,SFPBUFFW2 ;Upper word
CALL HEX16OUT ;Show it
CALL STD_SPACE ;Skip space
POP AX ;Restore registers
POP CX
POP DX
RET
FLOAT ENDP
;-----------------------------------------------------------------------------
;Convert from external to internal floating point
FPIN PROC FAR
PUSH DI ;Save registers
PUSH SI
PUSH DX
PUSH CX
PUSH AX
;
;Clear FPTEMP1 buffer
LEA DI,FPTEMP1 ;Point to FPTEMP1
MOV AL,0 ;Digit = 0
CALL FPINDIGIT ;Store digit
;
;Clear the decimal flag and the count
MOV DECFLAG,0 ;Clear flag
MOV DECEXP,0 ;Clear decimal exponent
;
;Look for the sign
CALL STD_IN
CMP AL,'-' ;Minus ?
JZ FPIN1 ;Store it
CMP AL,'+' ;Plus ?
JZ FPIN2 ;Ignore it
JMP FPIN3 ;Anything else gets used
;
;Set sign as negative
FPIN1:
MOV FPTEMP1B10,80H ;Put sign in place
FPIN2:
CALL STD_IN ;Get next digit
FPIN3:
CMP AL,'.' ;Check for a decimal place
JNE FPIN4 ;If not, continue
;
;Set decimal flag
CMP DECFLAG,0 ;Decimal flag already set?
JNE FPIN5 ;Exit if not the first
MOV DECFLAG,0FFH ;Set it now
JMP FPIN2 ;Go back for a digit
FPIN4:
SUB AL,30H ;Subtract 30H
JL FPIN5 ;Too low ?
CMP AL,9
JG FPIN5 ;Too high ?
JMP FPIN6 ;Got a digit
FPIN5:
JMP FPIN15 ;End of mantissa
;
;Load digit as a floating point number
FPIN6:
LEA DI,FPTEMP2 ;Point to FPTEMP2
CALL FPINDIGIT ;Put in the digit
;
;Multiply result by 10
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTMUL ;Multiply by 10
;
;Pick one with larger exponent
MOV CX,FPTEMP1W11 ;Get sign of FPTEMP1
SUB CX,FPTEMP2W11 ;Subtract sign of FPTEMP2
JE FPIN11 ;Skip if equal
JG FPIN9 ;If exponent FPTEMP2 is less
;
;Exponent of FPTEMP1 is less than exponent of FPTEMP2
FPIN7:
NEG CX ;Absolute value of exponent
;
;Shift the bits
FPIN8:
SAR FPTEMP1W8,1 ;Shift all bits right
RCR FPTEMP1W6,1 ;Carry on
RCR FPTEMP1W4,1
RCR FPTEMP1W2,1
RCR FPTEMP1W0,1
LOOP FPIN8
;
;Set the exponent
FPIN9:
MOV AX,FPTEMP2W11 ;Get exponent of FPTEMP2
MOV FPTEMP1W11,AX ;Put in exponent of FPTEMP1
JMP FPIN11 ;Done with this case
;
;Exponent of FPTEMP2 is less than exponent of FPTEMP1
;
;Shift the bits
FPIN10:
SAR FPTEMP2W8,1 ;Shift all bits right
RCR FPTEMP2W6,1 ;Carry on
RCR FPTEMP2W4,1
RCR FPTEMP2W2,1
RCR FPTEMP2W0,1
LOOP FPIN10
;
;Set the exponent
MOV AX,FPTEMP1W11 ;Get exponent of FPTEMP1
MOV FPTEMP2W11,AX ;Put in exponent of FPTEMP2
JMP FPIN11 ;Done with this case
;
;Add the digit to the result
FPIN11:
MOV CX,5 ;For a count of 5 words
LEA DI,FPTEMP1 ;DI points to FPTEMP1
LEA SI,FPTEMP2 ;SI points to FPTEMP2
CLC
FPIN12:
MOV AX,[SI] ;Get 16-bit digit from FPTEMP1
INC SI ;Point to next 16-bit digit
INC SI
ADC [DI],AX ;Add to 16-bit digit of FPTEMP2
INC DI ;Point to next 16-bit digit
INC DI
LOOP FPIN12
;
;Normalize
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTNORM ;Renormalize it
;
;Decrement decimal exponent if dec flag is on
FPIN13:
CMP DECFLAG,0 ;Check decimal flag
JE FPIN14 ;Skip if not set
DEC DECEXP ;Decrement exponent if set
FPIN14:
JMP FPIN2 ;Go back for next digit
;
;Adjust for the decimal point
FPIN15:
ADD AL,30H ;Restore ASCII
AND AL,5FH ;Upper or lower case
CMP AL,'E' ;Is it 'E' for exponent ?
JNE FPIN16
;
;Get exponent
CALL SGNDEC16IN ;Get signed decimal exponent
ADD DECEXP,DX ;Add it to current value
;
;Check for sign of decimal exponent
FPIN16:
MOV CX,DECEXP ;Get decimal exponent
CMP CX,0 ;Check its sign
JG FPIN17 ;If positive
JL FPIN18 ;If negative
;
;Zero count
JMP FPIN_XIT ;Done if exponent is zero
;
;Positive decimal exponent
FPIN17:
PUSH CX ;Save count = decimal exponent
;
;Multiply result by 10
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTMUL ;Multiply by 10
;
;Normalize
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTNORM ;Renormalize it
POP CX ;Restore the count
LOOP FPIN17
JMP FPIN_XIT ;End of this case
;
;Negative count
FPIN18:
NEG CX ;Absolute value of exponent
FPIN19:
PUSH CX ;Save the count = exponent
;
;Divide mantissa by 10
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTDIV ;Divide by 10
;
;Normalize
LEA DI,FPTEMP1 ;Point to FPTEMP1
CALL FPTNORM ;Renormalize it
POP CX ;Restore the count
LOOP FPIN19
;
FPIN_XIT:
CALL TFP2SFP ;Convert to single precision
POP AX ;Restore registers
POP CX
POP DX
POP SI
POP DI
RET
FPIN ENDP
;-----------------------------------------------------------------------------
;Convert an input single decimal digit to floating point
FPINDIGIT PROC NEAR
;
;Clear the number first
PUSH DI ;Save pointer
PUSH AX ;Save digit
MOV AL,0 ;Zero byte
MOV CX,13 ;Do 13 bytes
FPINDIGIT1:
MOV [DI],AL ;Clear the byte
INC DI ;Point to next byte
LOOP FPINDIGIT1 ;Loop for more
POP AX ;Restore digit
POP DI ;Restore pointer
;
;Move the digit into place
MOV [DI+9],AL ;Place the digit
RET
FPINDIGIT ENDP
;-----------------------------------------------------------------------------
;Convert from internal to external floating point
FPOUT PROC FAR
PUSH DI ;Save registers
PUSH SI
PUSH DX
PUSH BX
PUSH CX
PUSH AX
;
;Check for zero as a special case
MOV AX,SFPBUFFW0 ;Get low word
OR AX,SFPBUFFW2 ;Get high word
JNZ FPOUT1 ;Go on, if not zero
MOV AL,'0' ;Make a zero
CALL STD_OUT ;Send it out
JMP FPOUT_XIT ;And exit
;
;Convert from single precision to temporary floating point
FPOUT1:
CALL SFP2TFP ;Convert to temporary format
;
;Initialize exponent for un-normalized position
MOV DECEXP,21 ;Exponent = 21 for start
;
;Set the sign
MOV AL,FPTEMP1B10 ;Get sign
MOV DECSIGN,AL ;Put it away
;
;Convert mantissa to a decimal string
LEA SI,FPTEMP1 ;SI points to FPTEMP1
LEA DI,DECBUFF ;DI points to DECBUFF
CALL BIN802DEC ;Make decimal string
;
;Check sign of binary exponent
MOV CX,FPTEMP1W11 ;Get the binary exponent
SUB CX,72 ;Biased by -72
CMP CX,0 ;Check its sign
JL FPOUT2 ;If negative
JG FPOUT4 ;If positive
JMP FPOUT5 ;If zero
FPOUT3:
PUSH CX ;Absolute value of exponent
;
;Divide by 2
LEA DI,DECBUFF ;Point to DECBUFF
CALL DECHALF ;Divide by 2
;
;Normalize
LEA DECBUFF ;Point to DECBUFF
CALL DECNORM ;Renormalize
POP CX ;Restore count
LOOP FPOUT3
JMP FPOUT5 ;End of case
;
;Binary exponent is positive
FPOUT4:
PUSH CX ;Save count = binary exponent
;
;Multiply by 2
LEA DI,DECBUFF ;Point to DECBUFF
CALL DECDOUBLE ;Multiply by 2
;
;Normalize
LEA DECBUFF ;Point to DECBUFF
CALL DECNORM ;Renormalize
POP CX ;Restore count
LOOP FPOUT4
JMP FPOUT5 ;End of case
;
;Output the number
FPOUT5:
CALL TDECSHOW ;Display the number
FPOUT_XIT:
POP AX ;Restore registers
POP CX
POP BX
POP DX
POP SI
POP DI
RET
FPOUT ENDP
;-----------------------------------------------------------------------------
;Divide a temporary floating point by 10
FPTDIV PROC NEAR
;
;Shift mantissa by 4 places
MOV CX,4 ;For a count of 4
FPTDIV1:
SAL DIWORD+0,1 ;Shift all digits left
RCL DIWORD+2,1 ;Carry on
RCL DIWORD+4,1
RCL DIWORD+6,1
RCL DIWORD+8,1
DEC DIWORD+11
LOOP FPTDIV1
;
;Divide mantissa by 10
MOV CX,5 ;5 words in number
MOV DX,0 ;Previous remainder
ADD DI,8 ;Point to end
FPTDIV2:
PUSH CX ;Save count
MOV AX,[DI] ;Get 16-bit digit
MOV CX,10 ;Divisor of 10
DIV CX ;Divide
MOV [DI],AX ;Put 16-bit digit back
SUB DI,2 ;Next 16-bit digit
POP CX ;Restore count
LOOP FPTDIV2
RET
FPTDIV ENDP
;-----------------------------------------------------------------------------
;Multiply a temporary floating point by 10
FPTMUL PROC NEAR
MOV CX,5 ;For a count of 5
MOV DX,0 ;Carry of zero
FPTMUL1:
PUSH CX ;Save count
MOV AX,DX ;Previous carry
XCHG AX,[DI] ;Switch with 16-bit digit
MOV DX,10 ;Multiplier of 10
MUL CX ;Multiply
ADD [DI],AX ;Add into carry in place
ADD DI,2 ;Next 16-bit digit
POP CX ;Restore count
LOOP FPTMUL1
RET
FPTMUL ENDP
;-----------------------------------------------------------------------------
;Normalize a temporary floating point
FPTNORM PROC NEAR
CMP DIWORD+8,100H ;Test if too high
JL FPTNORM_XIT ;Exit if low enough
SAR DIWORD+8,1 ;Shift right all bytes
RCR DIWORD+6,1 ;Carry on
RCR DIWORD+4,1
RCR DIWORD+2,1
RCR DIWORD+0,1
INC DIWORD+11 ;Increment exponent
FPTNORM_XIT:
RET
FPTNORM ENDP
;-----------------------------------------------------------------------------
;Routine to convert from single to double precision floating point
SFP2DFP PROC FAR
PUSH AX ;Save register
;
;Clear low part of mantissa
MOV DFPBUFFW0,0 ;Clear low word
MOV DFPBUFFW2,0 ;Clear next low word
;
;Move rest of number
MOV AX,SFPBUFFW0 ;Get word from single precision
MOV DFPBUFFW4,AX ;Put in double precision
MOV AX,SFPBUFFW2 ;Get word from single precision
MOV DFPBUFFW6,AX ;Put in double precision
POP AX ;Restore registers
RET
SFP2DFP ENDP
;-----------------------------------------------------------------------------
;Routine to convert from single precision to temporary floating point
SFP2TFP PROC NEAR
;
;Clear lower part of mantissa
MOV FPTEMP1W0,0 ;Clear word
MOV FPTEMP1W2,0 ;Clear word
MOV FPTEMP1W4,0 ;Clear word
;
;Move rest of mantissa
MOV AX,SFPBUFF20 ;Low 2 bytes
MOV FPTEMP1W6,AX ;Put in place
MOV AX,SFPBUFFW2 ;High 7 bits
AND AX,007FH ;Remove sign
OR AX,0080H ;Restore MSB
MOV FPTEMP1W8,AX ;Put in place
;
;Move sign
MOV AL,SFPBUFFB2 ;In upper byte
AND AL,80H ;Just sign bit
MOV FPTEMP1B10,AL ;Byte 10 of FPTEMP1
;
;Move exponent
MOV AL,SFPBUFFB3 ;Byte 3 of SFP
MOV AH,0 ;Make into a word
SUB AX,80H ;Remove bias
MOV FPTEMP1W11,AX ;Its 16-bit 2's complement
RET
SFP2TFP ENDP
;-----------------------------------------------------------------------------
;Routine to convert from ASCII signed decimal to binary
SGNDEC16IN PROC FAR
MOV DX,0 ;Initialize DX as 0
MOV CH,0 ;Sign flag
CALL STD_IN ;Look for sign
CMP AL,'-' ;Minus ?
JZ SGNDEC16IN1 ;Store it
CMP AL,'+' ;Plus ?
JZ SGNDEC16IN2 ;Ignore it
JMP SGNDEC16IN3 ;Anything else gets used
;
;Set sign as negative
SGNDEC16IN1:
MOV CH,0FFH ;0FFH is -1
;Normal loop
SGNDEC16IN2:
CALL STDIN ;Digit comes in AL
;Already have a digit ?
SGNDEC16IN3:
SUB AL,30H ;Subtract 30H
JL SGNDEC16IN4 ;Check if too low
CMP AL,9
JG SGNDEC16IN4 ;Check if too high
CBW ;Convert to word
PUSH CX ;Save sign
PUSH AX ; and digit
MOV AX,DX
MOV CX,10 ;Multiplier of 10
MUL CX ;Multiply
MOV DX,AX ;Result in DX
POP AX ;Restore digit
ADD DX,AX ;Add in digit
POP CX ;Restore count
JMP SGNDEC16IN2
;
;Resolve the sign
SGNDEC16IN4:
CMP CH,0 ;Is it there ?
JE SGNDEC16IN_XIT ;If not, skip
NEG DX ;It was negative
SGNDEC16IN_XIT:
RET
SGNDEC16IN ENDP
;-----------------------------------------------------------------------------
;Routine to display floating point
TDECSHOW PROC NEAR
;
;Output the sign
CMP DECSIGN,0 ;Is it there ?
MOV AL,' ' ;Space if not
JE TDECSHOW1
;
;Output a minus sign
MOV AL,'-' ;Minus sign
TDECSHOW1:
CALL STD_OUT ;Send it out
;
;Output the first digit and a decimal point
TDECSHOW2:
LEA SI,DECBUFF+21 ;Point to first digit
MOV AL,[SI] ;Get it
DEC SI ;Point to next digit
ADD AL,30H ;Make it ASCII
CALL STD_OUT ;Send it out
;
;Output the rest of the decimal string
MOV CX,7 ;Only 7 more digits
TDECSHOW3:
MOV AL,[SI] ;Get digit
DEC SI ;Point to next digit
ADD AL,30H ;Make ASCII
CALL STD_OUT ;Send it out
LOOP TDECSHOW3
MOV AL,'E' ;E for exponent
CALL STD_OUT ;Send it
;
;Now the exponent
MOV DX,DECEXP ;Get exponent
CMP DX,0 ;Check sign
MOV AL,'+' ;Plus sign
JGE TDECSHOW_XIT ;If non-negative
;
;If negative exponent
NEG DX ;Absolute value of exponent
MOV AL,'-' ;Minus sign
TDECSHOW_XIT:
CALL STD_OUT ;Output sign of exponent
CALL DEC16OUT ;Output exponent
RET
TDECSHOW ENDP
;-----------------------------------------------------------------------------
;Routine to convert from temporary floating point to single precision
TFP2SFP PROC NEAR
;
;Move mantissa
MOV AX,FPTEMP1W4 ;Below word
RCL AX,1 ;Carry for round up
MOV AX,FPTEMP1W6 ;Low word
ADC AX,0 ;Low word + carry
MOV SFPBUFFW0,AX ;Put in place
MOV DX,AX ;Check for zero
MOV AX,FPTEMP1W8
OR DX,AX ;Check this part, too
AND AX,007FH ;Just bottom 7 bits
MOV SFPBUFFW2,AX ;Put in place
;
;Move sign bit
MOV AL,FPTEMP1B10 ;Byte 10 is sign
AND AL,80H
OR SFPBUFFB2,AL ;Bit 7 is sign
;
;Move exponent
MOV AX,FPTEMP1W11 ;16-bit 2's complement exponent
CMP AX,-128 ;Too low ?
JL TFP2SFP2 ;Error message
CMP AX,127 ;Too high ?
JG TFP2SFP3 ;Error message
ADD AX,80H ;Bias
CMP DX,0 ;Is mantissa 0 ?
JNE TFP2SFP1
MOV AL,0 ;Put biased byte back
;
;Normal return
;Show hex for debugging
LEA SI,INTERNAL ;Point to message
CALL STDMSG_OUT ;Send message
MOV DX,SFPBUFFW2 ;Upper word
CALL HEX16OUT ;Show it
MOV DX,SFPBUFFW0 ;Lower word
CALL HEX16OUT ;Show it
CALL STD_SPACE ;Skip space
CLC ;Clear carry
RET
;
;Underflow error
TFP2SFP2:
LEA SI,UNDERFLOW ;Point to message
JMP TFP2SFP4
;
;Overflow error
TFP2SFP3:
LEA SI,OVERFLOW ;Point to message
JMP TFP2SFP4
TFP2SFP_XIT:
CALL STDMSG_OUT ;Send message
STC ;Set carry
RET
TFP2SFP ENDP
;-----------------------------------------------------------------------------
;_____________________________________________________________________________
;
CODES ENDS
;
END
;_____________________________________________________________________________
;>>>>> Physical EOF FLOATPT.ASM <<<<<